
#include "HJM_Observer.hpp"

HJM_Observer::HJM_Observer ( HJM* p_subject, const pair < string,vector<double> >& p_elem ) :
  ThreadedObserver(p_subject), vsum(0), count(0)
{
  m_name = p_elem.first;
  data = p_elem.second;

  // check incoming data
  if ( m_name == "Caplet" )
    {
      type = Caplet;
      if ( data.size() < 3 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Caplet - insufficient data."));
    } 
  else if ( m_name == "Floorlet" )
    {
      type = Floorlet;
      if ( data.size() < 3 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Floorlet - insufficient data."));
    }
  else if ( m_name == "Libor" )
    {
      type = Libor;
      if ( data.size() < 2 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Libor - insufficient data."));
    }
  else if ( m_name == "ZCB" )
    {
      type = ZCB;
      if ( data.size() < 1 )
	throw (runtime_error("HJM_Observer::HJM_Observer: ZCB - insufficient data."));
    }
  else if ( m_name == "Call" )
    {
      type = Call;
      if ( data.size() < 2 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Call - insufficient data."));
    }
  else if ( m_name == "Swap" )
    {
      type = Swap;
      if ( data.size() < 2 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Swap - insufficient data."));
    }
  else if ( m_name == "Swaption" )
    {
      type = Swaption;
      if ( data.size() < 2 )
	throw (runtime_error("HJM_Observer::HJM_Observer: Swaption - insufficient data."));
    }
  else
    throw (runtime_error("HJM_Observer::HJM_Observer: unknown type."));
  
  m_subject->attach(this);
}
void HJM_Observer::update(int ith)
{
  if ( ! m_subject )
    throw (runtime_error("HJM_Observer::update: no subject."));

  HJM* hjm = dynamic_cast<HJM*>(m_subject);
  if ( ! hjm )
    throw (runtime_error("HJM_Observer::update: no subject."));

  if ( type == Caplet )
    {
      vsum += hjm->Caplet(ith,data[0],data[1],data[2]);
    }
  else if ( type == Floorlet )
    {
      vsum += hjm->Floorlet(ith,data[0],data[1],data[2]);
    }
  else if ( type == Libor )
    {
      vsum += hjm->Libor(ith,data[0],data[1]);
    }
  else if ( type == ZCB )
    {
      vsum += hjm->ZCB(ith,data[0]);
    }
  else if ( type == Call )
    {
      vsum += hjm->Call(ith,data[0],data[1]);
    }
  else if ( type == Swap )
    {
      vsum += hjm->Swap(ith,data[0],data[1]);
    }
  ++count;
}

double HJM_Observer::value()
{
  return vsum / count;
}
